package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

// 参考: https://studygolang.com/articles/12566
func work(ctx context.Context, wg *sync.WaitGroup) error {
	defer wg.Done()
	for {
		// 存在 default ,导致 for 一直循环
		select {
		case <-ctx.Done(): // 当调用 cancel,或者超时 执行
			fmt.Println("触发超时操作或者被取消")
			return ctx.Err()
		default:
			time.Sleep(time.Second * 1)
			fmt.Println("hello", time.Now().Unix())
		}
	}
}
func main() {

	//ctx := context.WithValue(context.Background(),"abc","test")
	//ctx,cancel := context.WithCancel(context.Background())
	//ctx,cancel := context.WithDeadline(context.Background(), time.Now().Add(2 * time.Second))

	//  sync.WaitGroup 类似队列
	var wg sync.WaitGroup
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	for i := 0; i < 10; i++ {
		wg.Add(1)
		//cancel() // cancel
		go work(ctx, &wg)
	}
	// 如果这里超时执行完,内 cancel了,则执行 work 里面 ctx.Done()
	time.Sleep(time.Second * 3)
	// 3s 后取消,也就是说, work 死循环,只执行 3s ,并且最终会打印10个 ctx.Done 选项内的数据
	cancel()  // cancel
	wg.Wait() //队列计数器为0的时候,取消等待

}
